import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class irGenerator {
    private FileWriter out; // 文件写入
    private int var_num; //中间代码变量序号,全为i32*
    private HashMap<String, Integer> priority;//运算符优先级
    private varBlock varBlock;//变量范围块
    private whileBlockRecord whileBlockRecord;//while语句块label记录
    private int get_num = 0;//调用函数的次数,用来添加在函数名末尾,区别多次调用的不同值
    private StringBuilder init_content = new StringBuilder();
    private StringBuilder get_func_params = new StringBuilder();
    private HashMap<String, func> defined_func;//定义的函数

    public irGenerator(FileWriter out) {
        this.out = out;
        this.var_num = 1;
        varBlock = new varBlock();//全局变量块
        whileBlockRecord = null;
        varBlock.outerBlock = null;
        defined_func = new HashMap<>();
        //运算符优先级
        this.priority = new HashMap<>();
        priority.put("Div", 2);
        priority.put("Mult", 2);
        priority.put("Plus", 1);
        priority.put("Minus", 1);
        priority.put("LPar", 4);
        priority.put("RPar", 4);
        priority.put("Mod", 2);
        priority.put("Not", 3);
    }

    //添加函数declare
    public void pre_write() throws IOException {
        String content = "declare i32 @getint()\ndeclare i32 @getch()\n" +
                "declare void @putint(i32)\ndeclare void @putch(i32)\n" +
                "declare void @memset(i32*, i32, i32)\ndeclare void @putarray(i32, i32*)\n" +
                "declare i32 @getarray(i32*)\n";
        out.write(content);
    }

    //添加全局数组的赋值
    public void init_write() throws IOException {
        out.write(init_content.toString());
    }

    //生成中间代码主方法
    public void generate(AST node) throws IOException {//递归遍历语法树
        write_CompUnit(node.getNode().get(0));
    }

    //compUnit中间代码生成
    public void write_CompUnit(AST comUnit_node) throws IOException {
        for (AST node : comUnit_node.getNode()) {
            if (node.getName().equals("Decl")) {
                write_GlobalVar(node);
            } else if (node.getName().equals("FuncDef")) {
                write_FuncDef(node);
            }
        }
    }

    //global var代码生成
    public void write_GlobalVar(AST decl_node) throws IOException {
        AST subNode = decl_node.getNode().get(0);
        if (subNode.getName().equals("ConstDecl")) {
            write_ConstDecl(subNode);
        } else {
            write_VarDecl(subNode);
        }
    }

    //funcDef中间代码生成
    public void write_FuncDef(AST funcDef_node) throws IOException {
        AST FuncType = funcDef_node.getNode().get(0).getNode().get(0);
        AST Ident = funcDef_node.getNode().get(1).getNode().get(0);
        AST Block = funcDef_node.getNode().get(4);
        varBlock v = new varBlock();
        v.outerBlock = this.varBlock;
        this.varBlock = v;//进入局部变量块
        if (Ident.getName().equals("Main")) {
            pre_write();//写函数调用的声明
            out.write("define i32 @main(){\n");
            init_write();//全局数组变量的赋值语句
            write_Block(Block);//代码块
            out.write("ret i32 0\n");
            out.write("}\n");
        } else {
            out.write("define ");
            String funcType = "";
            if (FuncType.getName().equals("Int")) {
                out.write("i32 ");
                funcType = "i32";
            } else {
                out.write("void ");
                funcType = "void";
            }
            out.write("@" + getIdent(Ident.getName()) + "(");//函数名
            func f = new func(getIdent(Ident.getName()), funcType);
            defined_func.put(getIdent(Ident.getName()), f);//储存定义的函数
            if (funcDef_node.getNode().get(3).getName().equals("FuncFParams"))//参数定义
                f.params_type = write_FuncFParams(funcDef_node.getNode().get(3));
            out.write("){\n");
            out.write(get_func_params.toString());//将传入的变量转为i32*的语句写入
            get_func_params = new StringBuilder();//重置记录
            write_Block(funcDef_node.getNode().get(funcDef_node.getNode().size() - 1));//代码块
            if (FuncType.getName().equals("Void")) out.write("ret void\n");//void函数保证最后有ret
            else out.write("ret i32 0\n");
            out.write("}\n");
        }
        this.varBlock = this.varBlock.outerBlock;//去除内部变量块,离开局部变量块
    }

    //函数定义中的定义
    public ArrayList<String> write_FuncFParams(AST FuncFParams_node) throws IOException {
        int size = FuncFParams_node.getNode().size();
        ArrayList<String> params_type = new ArrayList<>();
        params_type.add(write_FuncFParam(FuncFParams_node.getNode().get(0)));
        for (int i = 2; i < size; i += 2) {
            out.write(", ");
            params_type.add(write_FuncFParam(FuncFParams_node.getNode().get(i)));
        }
        return params_type;
    }

    //
    public String write_FuncFParam(AST FuncFParam_node) throws IOException {
        AST ident = FuncFParam_node.getNode().get(1).getNode().get(0);
        if (FuncFParam_node.getNode().size() == 2) {
            String var = "%x" + var_num++;
            out.write("i32 " + var);
            String var_star = "%x" + var_num++;
            get_func_params.append(var_star + " = alloca i32\n");
            get_func_params.append("store i32 " + var + ", i32* " + var_star + "\n");
            varBlock.add_constVars(getIdent(ident.getName()), var_star);
            return "i32";
        } else {
            String var = "%x" + var_num++;
            arrayIdent array = new arrayIdent(getIdent(ident.getName()));
            array.var = var;
            varBlock.add_varArrays(getIdent(ident.getName()), array);
            array.add_dim(0);//缺第一维补0
            int size = FuncFParam_node.getNode().size();
            for (int i = 5; i < size; i += 3) {//从有维数的开始,获取维数
                array.add_dim(to_int(get_Exp_Value(FuncFParam_node.getNode().get(i), true)));
            }
            type t = getArrayType(array.dim);
            out.write(t.innerType.toString() + "* " + var);//传入的数组
            array.type = t.innerType.toString() + "*";
            return t.innerType.toString() + "*";
        }
    }

    public String get_Exp_Value(AST Exp, boolean isConst) throws IOException {
        ArrayList<String> exp = Exp_RPN(Exp);
        Exp_irCode(exp, Exp, isConst);
        return Exp.getVar();
    }

    //constDef中间代码生成
    public void write_ConstDef(AST constDef_node) throws IOException {
        if (constDef_node.getNode().size() == 3) {//常量定义
            AST ident = constDef_node.getNode().get(0).getNode().get(0);
            AST ConstInitVal = constDef_node.getNode().get(2);
//            ArrayList<String> constExp = Exp_RPN(ConstInitVal);
//            Exp_irCode(constExp, ConstInitVal, true);
            get_Exp_Value(ConstInitVal, true);
            if (varBlock.outerBlock == null) {
                if (!isNumber(ConstInitVal.getVar()))
                    err("write_ConstDef:global常量含有非常量值");
                out.write("@x" + var_num + " = constant i32 " + ConstInitVal.getVar() + "\n");
                varBlock.add_constVars(getIdent(ident.getContent()), "@x" + var_num);
            } else {
                out.write("%x" + var_num + " = alloca i32\n");
                out.write(ConstInitVal.getContent());
                varBlock.add_constVars(getIdent(ident.getContent()), "%x" + var_num);
                out.write("store i32 " + ConstInitVal.getVar() + ", i32* %x" + var_num + "\n");
            }
            //添加常量与值对应,方便之后的常量表达式里的常量折叠
            varBlock.add_constVar_value(getIdent(ident.getContent()), to_int(ConstInitVal.getVar()));
            var_num++;
        } else {//数组定义
            String ident = getIdent(constDef_node.getNode().get(0).getNode().get(0).getContent());
            int i = 1;
            arrayIdent array = new arrayIdent(ident);
            while (constDef_node.getNode().get(i).getName().equals("LBracket")) {
                i++;//跳过前中括号
                AST dim_node = constDef_node.getNode().get(i);
//                ArrayList<String> constExp = Exp_RPN(dim_node);//纬度的逆波兰表达式
//                Exp_irCode(constExp, dim_node, true);
                get_Exp_Value(dim_node, true);
                if (!isNumber(dim_node.getVar()))
                    err("write_ConstDef:global数组纬度含有非常量值");
                if (to_int(dim_node.getVar()) <= 0)
                    err("write_ConstDef:数组纬度不能为负数");
                array.add_dim(to_int(dim_node.getVar()));//数组添加纬度
                i += 2;//跳过右中括号
            }
            i++;//跳过等号
            varBlock.add_constArrays(ident, array);//添加入代码块的变量储存中
            type t = getArrayType(array.dim);//获得type
            if (varBlock.outerBlock == null) {//全局数组声明
                String var = "@x" + var_num++;
                array.var = var;
                String init = getConstInitVal(constDef_node.getNode().get(i), t);//获取初始化的语句
                out.write(var + " = constant " + t.toString() + " " + init + "\n");//常量数组初始化语句
            } else {//局部数组声明
                String var = "%x" + var_num++;
                array.var = var;
                out.write(var + " = alloca " + t.toString() + "\n");
                ArrayList<String> params = new ArrayList<>();
                for (int j = 0; j < array.dim_num; j++) params.add(0 + "");//数组最开头的元素
                String head = getElement(array.ident, params, true, true);
                int total = 1;
                for (Integer s : array.dim) total *= s;
                out.write("call void @memset(i32* " + head + ", i32 0, i32 " + 4 * total + ")\n");
                write_constArray_assign(constDef_node.getNode().get(i), new ArrayList<>(), array.ident);
            }
        }
    }

    //常量数组赋值
    public void write_constArray_assign(AST ConstInitVal, ArrayList<String> params, String ident) throws IOException {
        if (ConstInitVal.getNode().get(0).getName().equals("ConstExp")) {
            AST constExp = ConstInitVal.getNode().get(0);
//            ArrayList<String> exp = Exp_RPN(constExp);
//            Exp_irCode(exp, constExp, true);
            get_Exp_Value(constExp, true);
            out.write(constExp.getContent());//表达式值的过程
            String point = getElement(ident, params, true, true);//对应位置的指针
            out.write("store i32 " + constExp.getVar() + ", i32* " + point + "\n");//赋值
        } else if (ConstInitVal.getNode().size() > 2) {
            int pos = 0;
            for (int i = 1; i < ConstInitVal.getNode().size(); i += 2) {
                ArrayList<String> p_ = new ArrayList<>(params);
                p_.add("" + pos++);
                write_constArray_assign(ConstInitVal.getNode().get(i), p_, ident);
            }
        }
    }

    //获取全局变量的初始化值的...
    public String getConstInitVal(AST ConstInitVal_node, type t) throws IOException {
        if (ConstInitVal_node.getNode().size() == 1 && ConstInitVal_node.getNode().get(0).getName().equals("ConstExp")) {
            AST constExp = ConstInitVal_node.getNode().get(0);
//            ArrayList<String> exp = Exp_RPN(constExp);
//            Exp_irCode(exp, constExp, true);
            get_Exp_Value(constExp, true);
            if (!isNumber(constExp.getVar()))
                err("getConstInitVal:含有非常量值");
            return constExp.getVar();
        } else if (ConstInitVal_node.getNode().size() == 2) {//为空的两个大括号
            return "zeroinitializer";
        } else {//递归调用getConstInitVal
            ArrayList<String> content = new ArrayList<>();
            int size = ConstInitVal_node.getNode().size();
            int count = 0;//记录本块的内容个数,不够则补
            for (int i = 1; i < size; i += 2) {//获取每一个constInitVal
                content.add(t.innerType.toString() + " " + getConstInitVal(ConstInitVal_node.getNode().get(i), t.innerType));
                count++;
            }
            if (t.innerType.dim.equals("i32")) {//缺少的纬度补纬度
                for (int i = count; i < to_int(t.dim); i++) {
                    content.add(t.innerType.toString() + " 0");
                }
            } else {
                for (int i = count; i < to_int(t.dim); i++) {
                    content.add(t.toString() + " zeroinitializer");
                }
            }
            String s = String.join(",", content);
            return "[" + s + "]";
        }
    }


    //获取数组的type
    public type getArrayType(ArrayList<Integer> dim) {
        type cur = new type("i32", null);
        for (int i = dim.size() - 1; i >= 0; i--) {
            cur = new type(dim.get(i) + "", cur);
        }
        return cur;
    }

    //varDef 中间代码生成
    public void write_VarDef(AST varDef_node) throws IOException {
        if (varDef_node.getNode().size() <= 3) {
            AST ident = getAST(varDef_node, "Ident").getNode().get(0);
            String ident_name = getIdent(ident.getContent());
            if (varBlock.outerBlock == null) {
                out.write("@x" + var_num + " = global i32 ");
                varBlock.add_vars(ident_name, "@x" + var_num);
                if (varDef_node.getNode().size() > 1) {
                    AST InitVal = varDef_node.getNode().get(2);
//                    ArrayList<String> initValExp = Exp_RPN(InitVal);
//                    Exp_irCode(initValExp, InitVal, true);
                    get_Exp_Value(InitVal, true);
                    if (!isNumber(InitVal.getVar()))
                        err("write_VarDef:global变量表达式含有非常量值");
                    out.write(InitVal.getVar() + "\n");
                } else {
                    out.write("0\n");//全局变量,无赋值初始化为0
                }
                var_num++;
            } else {
                out.write("%x" + var_num + " = alloca i32\n");
                varBlock.add_vars(ident_name, "%x" + var_num++);
                if (varDef_node.getNode().size() > 1) {
                    AST InitVal = varDef_node.getNode().get(2);
//                    ArrayList<String> initValExp = Exp_RPN(InitVal);
//                    Exp_irCode(initValExp, InitVal, false);
                    get_Exp_Value(InitVal, false);
                    out.write(InitVal.getContent());
                    out.write("store i32 " + InitVal.getVar() + ", i32* " + varBlock.find_var(ident_name) + "\n");
                }
            }
        } else {
            String ident = getIdent(getAST(varDef_node, "Ident").getNode().get(0).getContent());
            int i = 1;
            arrayIdent array = new arrayIdent(ident);
            while (i < varDef_node.getNode().size() && varDef_node.getNode().get(i).getName().equals("LBracket")) {
                i++;//跳过前中括号
                AST dim_node = varDef_node.getNode().get(i);
//                ArrayList<String> constExp = Exp_RPN(dim_node);//纬度的逆波兰表达式
//                Exp_irCode(constExp, dim_node, true);
                get_Exp_Value(dim_node, true);
                if (!isNumber(dim_node.getVar()))
                    err("write_ConstDef:global数组纬度含有非常量值");
                if (to_int(dim_node.getVar()) <= 0)
                    err("write_ConstDef:数组纬度不能小于等于0");
                array.add_dim(to_int(dim_node.getVar()));//数组添加纬度
                i += 2;//跳过右中括号
            }
            i++;//如果有等号则跳过等号
            varBlock.add_varArrays(ident, array);//添加入代码块的变量储存中
            type t = getArrayType(array.dim);//获得type
            if (varBlock.outerBlock == null) {//全局数组
                String var = "@x" + var_num++;
                array.var = var;
                out.write(var + " = global " + t.toString() + " zeroinitializer\n");
                if (i < varDef_node.getNode().size()) {
                    AST InitVal = varDef_node.getNode().get(i);
                    init_content.append(write_Array_assign(InitVal, new ArrayList<>(), array.ident, new StringBuilder(), true, false));
                }
            } else {//局部数组
                String var = "%x" + var_num++;
                array.var = var;
                out.write(var + " = alloca " + t.toString() + "\n");
                ArrayList<String> params = new ArrayList<>();
                for (int j = 0; j < array.dim_num; j++) params.add(0 + "");//数组最开头的元素
                String head = getElement(array.ident, params, true, false);
                int total = 1;
                for (Integer s : array.dim) total *= s;
                out.write("call void @memset(i32* " + head + ", i32 0, i32 " + 4 * total + ")\n");//初始化0值
                if (i < varDef_node.getNode().size()) {
                    AST InitVal = varDef_node.getNode().get(i);
                    out.write(write_Array_assign(InitVal, new ArrayList<>(), array.ident, new StringBuilder(), false, true));
                }
            }
        }
    }

    //变量数组赋值
    public String write_Array_assign(AST InitVal, ArrayList<String> params, String ident, StringBuilder content, boolean isConst, boolean isWrite) throws IOException {
        if (InitVal.getNode().get(0).getName().equals("Exp")) {
            AST Exp = InitVal.getNode().get(0);
//            ArrayList<String> exp = Exp_RPN(Exp);
//            Exp_irCode(exp, Exp, isConst);//当在全局初始化时必须为const,在变量块中随意
            get_Exp_Value(Exp, isConst);
            content.append(Exp.getContent());//表达式值的过程
            String point = getElement(ident, params, isWrite, false);//对应位置的指针,变量赋值,求此变量的ptr
            content.append("store i32 " + Exp.getVar() + ", i32* " + point + "\n");//赋值
        } else if (InitVal.getNode().size() > 2) {
            int pos = 0;
            for (int i = 1; i < InitVal.getNode().size(); i += 2) {
                ArrayList<String> p_ = new ArrayList<>(params);
                p_.add("" + pos++);
                write_Array_assign(InitVal.getNode().get(i), p_, ident, content, isConst, isWrite);
            }
        }
        return content.toString();
    }

    // stmt块的中间代码生成
    public void write_Stmt(AST stmt_node) throws IOException {
        if (stmt_node.getNode().get(0).getName().equals("Return")) {
            if (stmt_node.getNode().size() == 2) {//只有单return
                out.write("ret void\n");
            } else {
                AST exp_node = stmt_node.getNode().get(1);
                get_Exp_Value(exp_node, false);
                out.write(exp_node.getContent());
                out.write("ret i32 " + exp_node.getVar() + "\n");
            }
        } else if (stmt_node.getNode().get(0).getName().equals("LVal")) {
            write_LVal(stmt_node);
        } else if (stmt_node.getNode().get(0).getName().equals("Exp")) {
            write_singleExp(stmt_node.getNode().get(0));//传入exp结点
        } else if (stmt_node.getNode().get(0).getName().equals("If")) {
            write_If(stmt_node);
        } else if (stmt_node.getNode().get(0).getName().equals("Block")) {
            varBlock v = new varBlock();
            v.outerBlock = this.varBlock;
            this.varBlock = v;//进入局部变量块
            write_Block(stmt_node.getNode().get(0));//传入的是Block结点
            this.varBlock = this.varBlock.outerBlock;
        } else if (stmt_node.getNode().get(0).getName().equals("While")) {
            write_While(stmt_node);
        } else if (stmt_node.getNode().get(0).getName().equals("Break")) {
            out.write("br label %" + whileBlockRecord.next_block + "\n");
        } else if (stmt_node.getNode().get(0).getName().equals("Continue")) {
            out.write("br label %" + whileBlockRecord.cond_block + "\n");
        }
    }

    //block语句块
    public void write_Block(AST node) throws IOException {
//        varBlock v = new varBlock();
//        v.outerBlock = this.varBlock;
//        this.varBlock = v;//进入局部变量块
        int size = node.getNode().size();
        for (int i = 1; i < size - 1; i++) {
            write_BlockItem(node.getNode().get(i));
        }
//        this.varBlock = this.varBlock.outerBlock;//去除内部变量块,离开局部变量块
    }

    //blockitem语句块
    public void write_BlockItem(AST node) throws IOException {
        if (node.getNode().get(0).getName().equals("Stmt")) {
            write_Stmt(node.getNode().get(0));
        } else if (node.getNode().get(0).getName().equals("Decl")) {
            AST decl = node.getNode().get(0);
            if (decl.getNode().get(0).getName().equals("ConstDecl")) {
                write_ConstDecl(decl.getNode().get(0));
            } else if (decl.getNode().get(0).getName().equals("VarDecl")) {
                write_VarDecl(decl.getNode().get(0));
            }
        }
    }

    //constDecl
    public void write_ConstDecl(AST constDecl_node) throws IOException {
        int size = constDecl_node.getNode().size();
        for (int i = 2; i < size; i += 2) {
            write_ConstDef(constDecl_node.getNode().get(i));
        }
    }

    //varDecl
    public void write_VarDecl(AST varDecl_node) throws IOException {
        int size = varDecl_node.getNode().size();
        for (int i = 1; i < size; i += 2) {
            write_VarDef(varDecl_node.getNode().get(i));
        }
    }

    //if语句块中间代码
    public void write_If(AST node) throws IOException {
        boolean flag = false;//else flag
        AST LOrExp = node.getNode().get(2).getNode().get(0);
        AST stmt = node.getNode().get(4);
        AST else_stmt = null;
        if (node.getNode().size() > 5) {
            else_stmt = node.getNode().get(6);
            flag = true;
        }
        String if_num = "x" + var_num++;
        String else_num = "x" + var_num++;
        String next_block = "x" + var_num++;
        if (flag) {
            write_LOrExp(LOrExp, if_num, else_num);
//            out.write("br i1 " + LOrExp.getVar() + " ,label %" + if_num + ", label %" + else_num + "\n");
            out.write(if_num + ":\n");
            write_Stmt(stmt);
            out.write("br label %" + next_block + "\n");
            out.write(else_num + ":\n");
            write_Stmt(else_stmt);
            out.write("br label %" + next_block + "\n");
            out.write(next_block + ":\n");
            out.write("%x" + var_num++ + " = add i32 0, 0\n");//多余操作,防止空label
        } else {
//            out.write("br i1 " + LOrExp.getVar() + " ,label %" + if_num + ",label %" + next_block + "\n");
            write_LOrExp(LOrExp, if_num, next_block);
            out.write(if_num + ":\n");
            write_Stmt(stmt);
            out.write("br label %" + next_block + "\n");
            out.write(next_block + ":\n");
            out.write("%x" + var_num++ + " = add i32 0, 0\n");//多余操作,防止空label
        }
    }

    //while语句块中间代码
    public void write_While(AST node) throws IOException {
        AST LOrExp = node.getNode().get(2).getNode().get(0);
        AST Stmt = node.getNode().get(4);
        String cond_block = "x" + var_num++;
        String while_block = "x" + var_num++;
        String next_block = "x" + var_num++;
        //进入while块,保存label标签用于break和continue
        whileBlockRecord = new whileBlockRecord(cond_block, while_block, next_block, whileBlockRecord);
        out.write("br label %" + cond_block + "\n");
        out.write(cond_block + ":\n");
        write_LOrExp(LOrExp, while_block, next_block);
//        out.write("br i1 " + LOrExp.getVar() + ", label %" + while_block + ", label %" + next_block + "\n");
        out.write(while_block + ":\n");
        write_Stmt(Stmt);
        out.write("br label %" + cond_block + "\n");
        out.write(next_block + ":\n");
        out.write("%x" + var_num++ + " = add i32 0, 0\n");//多余操作,防止空label
        whileBlockRecord = whileBlockRecord.outerBlock;//离开本while
    }

    //或条件语句代码生成
    public void write_LOrExp(AST LOrExp, String do_block, String next_block) throws IOException {
        int size = LOrExp.getNode().size();
        int n = (size + 1) / 2;
        String next = "x" + var_num++;
        out.write("br label %" + next + "\n");
        for (int i = 0; i < n; i++) {
            out.write(next + ":\n");
            AST LAndExp = LOrExp.getNode().get(2 * i);
            next = "x" + var_num++;
            write_LAndExp(LAndExp, do_block, next);
        }
        out.write(next + ":\n");
        out.write("br label %" + next_block + "\n");
//        for (int i = 0; i < n; i++) {
//            AST LAndExp = LOrExp.getNode().get(2 * i);
//            write_LAndExp(LAndExp);
//        }
//        ArrayList<String> cmp_var = new ArrayList<>();
//        for (int i = 0; i < n; i++) {
//            cmp_var.add(LOrExp.getNode().get(2 * i).getVar());
//        }
//        //或运算
//        while (cmp_var.size() > 1) {
//            String r1 = cmp_var.remove(0);
//            String r2 = cmp_var.remove(0);
//            out.write("%x" + var_num + " = or i1 " + r1 + "," + r2 + "\n");
//            cmp_var.add(0, "%x" + var_num);
//            var_num++;
//        }
//        LOrExp.setVar(cmp_var.remove(0));
    }

    //与条件语句代码生成
    public void write_LAndExp(AST LAndExp, String do_block, String next_block) throws IOException {
        int size = LAndExp.getNode().size();
        int n = (size + 1) / 2;
        String next = "x" + var_num++;
        out.write("br label %" + next + "\n");
        for (int i = 0; i < n; i++) {
            out.write(next + ":\n");
            AST EqExp = LAndExp.getNode().get(2 * i);
            write_EqExp(EqExp);
            String ans = EqExp.getVar();
            next = "x" + var_num++;
            out.write("br i1" + ans + ", label %" + next + ", label %" + next_block + "\n");
        }
        out.write(next + ":\n");
        out.write("br label %" + do_block + "\n");
//        for (int i = 0; i < n; i++) {
//            AST EqExp = LAndExp.getNode().get(2 * i);
//            write_EqExp(EqExp);
//        }
//        ArrayList<String> cmp_var = new ArrayList<>();
//        for (int i = 0; i < n; i++) {
//            cmp_var.add(LAndExp.getNode().get(2 * i).getVar());
//        }
//        //比较结果与运算
//        while (cmp_var.size() > 1) {
//            String r1 = cmp_var.remove(0);
//            String r2 = cmp_var.remove(0);
//            out.write("%x" + var_num + " = and i1 " + r1 + "," + r2 + "\n");
//            cmp_var.add(0, "%x" + var_num);
//            var_num++;
//        }
//        LAndExp.setVar(cmp_var.remove(0));
    }

    //等条件语句代码生成
    //由于再外面的条件判断都为逻辑判断,所以这里直接保存var为i1形式.
    public void write_EqExp(AST EqExp) throws IOException {
        int size = EqExp.getNode().size();
        int n = (size + 1) / 2;
        for (int i = 0; i < n; i++) {
            AST RelExp = EqExp.getNode().get(2 * i);
            write_RelExp(RelExp);
        }
        if (size == 1) {
            //如果为纯数字,转i32为i1,return
            AST RelExp = EqExp.getNode().get(0);
            String RelExp_Var = RelExp.getVar();
            out.write("%x" + var_num + " = icmp ne i32 0," + RelExp_Var + "\n");
            EqExp.setVar("%x" + var_num);
            var_num++;
            return;
        }
        ArrayList<String> cmp_var = new ArrayList<>();
        for (int i = 0; i < n - 1; i++) {
            AST indent = EqExp.getNode().get(2 * i + 1);
            String RelExp_Var1 = EqExp.getNode().get(2 * i).getVar();
            String RelExp_Var2 = EqExp.getNode().get(2 * i + 2).getVar();
            String op = "";
            switch (indent.getName()) {
                case "Eq" -> op = "eq";
                case "NotEq" -> op = "ne";
            }
            out.write("%x" + var_num + " = icmp " + op + " i32 " + RelExp_Var1 + "," + RelExp_Var2 + "\n");
            cmp_var.add("%x" + var_num);
            var_num++;
        }
        //比较结果与运算
        while (cmp_var.size() > 1) {
            String r1 = cmp_var.remove(0);
            String r2 = cmp_var.remove(0);
            out.write("%x" + var_num + " = and i1 " + r1 + "," + r2 + "\n");
            cmp_var.add(0, "%x" + var_num);
            var_num++;
        }
        EqExp.setVar(cmp_var.remove(0));
    }

    //真值条件语句代码生成
    //Var里保存的i32的值,因为可能有纯数字,可能有==判断
    public void write_RelExp(AST RelExp) throws IOException {
        int size = RelExp.getNode().size();
        int n = (size + 1) / 2;
        for (int i = 0; i < n; i++) {
            AST AddExp = RelExp.getNode().get(2 * i);
//            ArrayList<String> exp_rpn = Exp_RPN(AddExp);
//            Exp_irCode(exp_rpn, AddExp, false);
            get_Exp_Value(AddExp, false);
            out.write(AddExp.getContent());
        }
        if (size == 1) {
            //如果为纯数字,return   i32
            AST AddExp = RelExp.getNode().get(0);
            RelExp.setVar(AddExp.getVar());
            return;
        }
        ArrayList<String> cmp_var = new ArrayList<>();
        // 连续比较两两比较 (3>4<5>4)
        for (int i = 0; i < n - 1; i++) {
            AST ident = RelExp.getNode().get(2 * i + 1);
            String AddExp_Var1 = RelExp.getNode().get(2 * i).getVar();
            String AddExp_Var2 = RelExp.getNode().get(2 * i + 2).getVar();
            String op = "";
            switch (ident.getName()) {
                case "Lt" -> op = "slt";
                case "Gt" -> op = "sgt";
                case "LessEq" -> op = "sle";
                case "GreatEq" -> op = "sge";
            }
            out.write("%x" + var_num + " = icmp " + op + " i32 " + AddExp_Var1 + "," + AddExp_Var2 + "\n");
            cmp_var.add("%x" + var_num);
            var_num++;
        }
        //比较结果与运算
        while (cmp_var.size() > 1) {
            String r1 = cmp_var.remove(0);
            String r2 = cmp_var.remove(0);
            out.write("%x" + var_num + " = and i1 " + r1 + "," + r2 + "\n");
            cmp_var.add(0, "%x" + var_num);
            var_num++;
        }
        //转换i1为i32
        out.write("%x" + var_num + " = zext i1 " + cmp_var.remove(0) + " to i32\n");
        RelExp.setVar("%x" + var_num);
        var_num++;
    }

    //单个表达式中间代码
    public void write_singleExp(AST exp) throws IOException {
//        ArrayList<String> exp_rpn = Exp_RPN(exp);
//        Exp_irCode(exp_rpn, exp, false);
        get_Exp_Value(exp, false);
        out.write(exp.getContent());
    }

    //LVal 赋值语句代码生成
    public void write_LVal(AST stmt_node) throws IOException {
        AST LVal_node = stmt_node.getNode().get(0);
        if (LVal_node.getNode().size() == 1) { //变量赋值
            AST ident_node = LVal_node.getNode().get(0).getNode().get(0);
            String ident = getIdent(ident_node.getName());
            AST exp = stmt_node.getNode().get(2);
//            ArrayList<String> exp_rpn = Exp_RPN(exp);
//            Exp_irCode(exp_rpn, exp, false);
            get_Exp_Value(exp, false);
            out.write(exp.getContent());
            out.write("store i32 " + exp.getVar() + " ,i32* " + varBlock.find_allVar(ident) + "\n");
        } else {//数组赋值
            String ident = getIdent(LVal_node.getNode().get(0).getNode().get(0).getContent());
            ArrayList<String> params = new ArrayList<>();
            for (int i = 2; i < LVal_node.getNode().size(); i += 3) {
                AST dim_node = LVal_node.getNode().get(i);
//                ArrayList<String> constExp = Exp_RPN(dim_node);//纬度的逆波兰表达式
//                Exp_irCode(constExp, dim_node, false);
                get_Exp_Value(dim_node, false);
                out.write(dim_node.getContent());//写入参数获取的过程
                params.add(dim_node.getVar());//获得维度参数
            }
            String var = getElement(ident, params, true, false);//数组对应位置的指针
            AST exp = stmt_node.getNode().get(2);//右边赋值语句
//            ArrayList<String> exp_rpn = Exp_RPN(exp);
//            Exp_irCode(exp_rpn, exp, false);
            get_Exp_Value(exp, false);
            out.write(exp.getContent());
            out.write("store i32 " + exp.getVar() + " ,i32*" + var + "\n");//储存值到数组对应位置
        }

    }

    //根据输入的纬度位置,获取该位置的数值指针,返回的为i32*类型
    public String getElement(String ident, ArrayList<String> params, boolean isWrite, boolean isConst) throws IOException {
        arrayIdent array;
        if (isConst)
            array = varBlock.find_constArray(ident);
        else
            array = varBlock.find_allArray(ident);
        StringBuilder s = new StringBuilder();
        if (array.dim_num != params.size())
            err("getElement:数组纬度不相符");
        type t = getArrayType(array.dim);
//        for (int i = array.dim.size() - 1; i >= 0; i--) {
//            type = "[" + array.dim.get(i) + " x " + type + "]";
//        }
        String type = t.toString();
        String var = "%x" + var_num++;
        s.append(var + " = getelementptr " + type + ", " + type + "* " + array.var);//+ ", i32 0"
        if (!type.equals("i32") && !(array.dim.get(0) == 0)) s.append(", i32 0");
        for (String param : params) {
            s.append(", i32 " + param);
        }
        s.append("\n");
        if (isWrite)
            out.write(s.toString());//直接输出
        else
            init_content.append(s.toString());//写入init_content,用于全局变量数组中值的初始化
        return var;
    }

    // 根据后缀表达式生成三元地址表达
    public void Exp_irCode(ArrayList<String> exp_rpn, AST node, boolean isConst) throws IOException {
        if (exp_rpn.size() == 0) {
            node.setContent("");
            return;
        }
        if (exp_rpn.size() == 1) { //单个值情况
            String content = "";
            if (Pattern.compile("\\d+").matcher(exp_rpn.get(0)).matches()) {
                node.setContent(content);//为纯数字,不需要content为空
                node.setVar(exp_rpn.remove(0));//var直接设为数字
                return;
            } else if (Pattern.compile("Ident").matcher(exp_rpn.get(0)).find()) {
                String ident = getIdent(exp_rpn.remove(0));
                if (isConst) {
                    if (!varBlock.constVar_contain(ident))
                        err("使用了未定义的常量");
                    node.setContent("");
                    node.setVar(varBlock.get_constVar_value(ident) + "");
                    return;
                } else {
                    String s = varBlock.find_allVar(ident);
                    if (s == null)
                        err("使用了未定义的变量或常量");
                    content = "%x" + var_num + " = load i32, i32* " + s + "\n";
                }
            } else if (exp_rpn.get(0).startsWith("$")) {
                content = "%x" + var_num + "= load i32, i32* " + varBlock.find_var(exp_rpn.remove(0)) + "\n";
            } else if (exp_rpn.get(0).startsWith("Array")) {
                String str = getIdent(exp_rpn.remove(0));//可以使用getIdent进行去壳,因为此函数提取的是括号里的
                String[] params = str.split(":");
                String ident = params[0];//第0个是数组名,后面是纬度参数
                ArrayList<String> p = new ArrayList<>(Arrays.asList(params));//转换为arraylist
                p.remove(0);//去掉name
                String v = getElement(ident, p, true, isConst);
                String var = "%x" + var_num++;
                out.write(var + " = load i32, i32* " + v + "\n");
                node.setContent("");
                node.setVar(var);
                return;
            }
            node.setContent(content);
            node.setVar("%x" + var_num++);
            return;
        }
        ArrayList<String> stack = new ArrayList<>();
        StringBuilder content = new StringBuilder();
        while (exp_rpn.size() > 0) {
            if (Pattern.compile("\\d+").matcher(exp_rpn.get(0)).matches()) {
                stack.add(0, exp_rpn.remove(0));
            } else if (Pattern.compile("Ident").matcher(exp_rpn.get(0)).find()) {
                String ident = getIdent(exp_rpn.remove(0));
                if (isConst) {
                    if (!varBlock.constVar_contain(ident))
                        err("Exp_irCode:引用常量未被赋值");
                    int a = varBlock.get_constVar_value(ident);
                    stack.add(0, a + "");
                } else {
                    if (varBlock.constVars_value.containsKey(ident)) {//变量表达式中含有常量直接替换成对应的值
                        int a = varBlock.get_constVar_value(ident);
                        stack.add(0, a + "");
                    } else {
                        String var = "%x" + var_num++;
                        out.write(var + " = load i32, i32* " + varBlock.find_allVar(ident) + "\n");
                        stack.add(0, var);
                    }
                }
            } else if (exp_rpn.get(0).startsWith("$")) {
                String var = "%x" + var_num++;
                out.write(var + " = load i32, i32* " + varBlock.find_var(exp_rpn.remove(0)) + "\n");
                stack.add(0, var);
            } else if (exp_rpn.get(0).startsWith("Array")) {
                String str = getIdent(exp_rpn.remove(0));//可以使用getIdent进行去壳,因为此函数提取的是括号里的
                String[] params = str.split(":");
                String ident = params[0];//第0个是数组名,后面是纬度参数
                ArrayList<String> p = new ArrayList<>(Arrays.asList(params));//转换为arraylist
                p.remove(0);//去掉name
                String v = getElement(ident, p, true, isConst);//i32*变量
                String var = "%x" + var_num++;//i32变量
                out.write(var + " = load i32, i32* " + v + "\n");
                stack.add(0, var);
            } else {
                switch (exp_rpn.remove(0)) {
                    case "Plus" -> {
                        String a2 = stack.remove(0);
                        String a1 = stack.remove(0);
                        if (isNumber(a1) && isNumber(a2)) {
                            int a = to_int(a1) + to_int(a2);
                            stack.add(0, a + "");
                        } else {
                            content.append("%x" + var_num + " = add i32 " + a1 + ", " + a2 + "\n");
                            stack.add(0, "%x" + var_num);
                            var_num++;
                        }
                    }
                    case "Minus" -> {
                        String a2 = stack.remove(0);
                        String a1 = stack.remove(0);
                        if (isNumber(a1) && isNumber(a2)) {
                            int a = to_int(a1) - to_int(a2);
                            stack.add(0, a + "");
                        } else {
                            content.append("%x" + var_num + " = sub i32 " + a1 + ", " + a2 + "\n");
                            stack.add(0, "%x" + var_num);
                            var_num++;
                        }
                    }
                    case "Mult" -> {
                        String a2 = stack.remove(0);
                        String a1 = stack.remove(0);
                        if (isNumber(a1) && isNumber(a2)) {
                            int a = to_int(a1) * to_int(a2);
                            stack.add(0, a + "");
                        } else {
                            content.append("%x" + var_num + " = mul i32 " + a1 + ", " + a2 + "\n");
                            stack.add(0, "%x" + var_num);
                            var_num++;
                        }
                    }
                    case "Div" -> {
                        String a2 = stack.remove(0);
                        String a1 = stack.remove(0);
                        if (isNumber(a1) && isNumber(a2)) {
                            int a = to_int(a1) / to_int(a2);
                            stack.add(0, a + "");
                        } else {
                            content.append("%x" + var_num + " = sdiv i32 " + a1 + ", " + a2 + "\n");
                            stack.add(0, "%x" + var_num);
                            var_num++;
                        }
                    }
                    case "Mod" -> {
                        String a2 = stack.remove(0);
                        String a1 = stack.remove(0);
                        if (isNumber(a1) && isNumber(a2)) {
                            int a = to_int(a1) % to_int(a2);
                            stack.add(0, a + "");
                        } else {
                            content.append("%x" + var_num + " = srem i32 " + a1 + ", " + a2 + "\n");
                            stack.add(0, "%x" + var_num);
                            var_num++;
                        }
                    }
                    case "Not" -> {
                        String a = stack.remove(0);
                        //纯数字
                        if (isNumber(a)) {
                            if (to_int(a) == 0)
                                stack.add(0, "1");
                            else
                                stack.add(0, "0");
                        } else {
                            content.append("%x" + var_num + " = icmp eq i32 0, " + a + "\n");
                            var_num++;
                            content.append("%x" + var_num + " = zext i1 %x" + (var_num - 1) + " to i32\n");
                            stack.add(0, "%x" + var_num);
                            var_num++;
                        }
                    }
                }
            }
        }
        node.setContent(content.toString());
        node.setVar(stack.remove(0));
        node.setLeaf(true);
    }


    // 逆波兰算法转换为后缀表达式
    public ArrayList<String> Exp_RPN(AST Exp_node) throws IOException {
        ArrayList<String> exp = new ArrayList<>();
        get_Exp(Exp_node, exp);
//        System.out.println(exp.toString());//中缀表达式
        ArrayList<String> operatorsStack = new ArrayList<>();
        ArrayList<String> output = new ArrayList<>();
        while (exp.size() > 0) {
            String token = exp.remove(0);
            // 若是数字则直接压到output里
            if (Pattern.compile("Number").matcher(token).find()) {
                output.add(Pattern.compile("[^0-9]").matcher(token).replaceAll(""));
            } else if (Pattern.compile("Ident").matcher(token).find()) {//是变量直接压栈
                output.add(token);
            } else if (Pattern.compile("Array").matcher(token).find()) {//是数组直接压栈
                output.add(token);
            } else {

                if (!token.equals("RPar")) {
                    // 符号栈为空或优先级大于栈顶优先级 则压入
                    while (!(operatorsStack.size() == 0) && priority.get(token) <= priority.get(operatorsStack.get(0))) {
                        if (operatorsStack.get(0).equals("LPar")) {
                            break;
                        }
                        output.add(operatorsStack.remove(0));
                    }
                    operatorsStack.add(0, token);
                } else {
                    // 若是右括号,符号栈弹出压到output直到左括号
                    while (true) {
                        String top = operatorsStack.remove(0);
                        if (top.equals("LPar")) {
                            break;
                        } else {
                            output.add(top);
                        }
                    }
                }
            }
        }
        // 将符号栈里剩余的压入output
        while (operatorsStack.size() > 0) {
            output.add(operatorsStack.remove(0));
        }
//        System.out.println(output.toString());//后缀表达式
        return output;
    }

    // 获取表达式
    public void get_Exp(AST Exp_node, ArrayList<String> exp) throws IOException {
        if (Exp_node.isLeaf()) {
            exp.add(Exp_node.getContent());
        } else {
            if (Exp_node.getName().equals("FuncCall")) {
                handle_FuncCall(Exp_node, exp);
                return;
            }
            if (Exp_node.getName().equals("LVal")) {
                handle_LVal(Exp_node, exp);
                return;
            }
            for (AST node : Exp_node.getNode()) {
                get_Exp(node, exp);
            }
        }
    }

    //LVal的代码单独解析,因为含有数组
    public void handle_LVal(AST node, ArrayList<String> exp) throws IOException {
        String ident = node.getNode().get(0).getNode().get(0).getContent();
        if (node.getNode().size() == 1) {
            exp.add(ident);
        } else {
            String name = getIdent(ident);//去除ident(  )
            ArrayList<String> params = new ArrayList<>();
            params.add(name);
            int size = node.getNode().size();
            for (int i = 2; i < size - 1; i += 3) {
                AST n = node.getNode().get(i);
//                ArrayList<String> e = Exp_RPN(n);
//                Exp_irCode(e, n, false);
                get_Exp_Value(n, false);
                out.write(n.getContent());
                params.add(n.getVar());
            }
            String p = String.join(":", params);
            exp.add("Array(" + p + ")");//使用 : 将数组名和数组纬度参数之间分开
        }
    }

    //函数调用代码生成
    public void handle_FuncCall(AST node, ArrayList<String> exp) throws IOException {
        AST ident = node.getNode().get(0).getNode().get(0);
        String ident_name = getIdent(ident.getName());
        if (ident_name.equals("getint") || ident_name.equals("getch")) {
            String var = "%x" + var_num++;
            String var_star = "%x" + var_num++;
            out.write(var + "= call i32 @" + ident_name + "()\n");
            out.write(var_star + " = alloca i32\n");
            out.write("store i32 " + var + ", i32* " + var_star + "\n");
            varBlock.add_vars("$" + ident_name + get_num, var_star);
            exp.add("Ident($" + ident_name + get_num++ + ")");
        } else if (ident_name.equals("putint") || ident_name.equals("putch")) {
            AST param = node.getNode().get(2).getNode().get(0);
            if (param.getName().equals("RPar") || param.getNode().size() > 1) {
                err("FuncCall:参数数量异常");
            }
            AST param_exp = param.getNode().get(0);
//            ArrayList<String> param_exp_rpn = Exp_RPN(param_exp);
//            Exp_irCode(param_exp_rpn, param_exp, false);
            get_Exp_Value(param_exp, false);
            out.write(param_exp.getContent());
            out.write("call void @" + ident_name + "(i32 " + param_exp.getVar() + ")\n");
        } else if (ident_name.equals("getarray")) {
            String var = "%x" + var_num++;
            String var_star = "%x" + var_num++;
            AST FuncRParams = node.getNode().get(2);
            AST LVal = getAST(FuncRParams, "LVal");
            if (LVal == null) err("handle_FuncCall:getarray参数错误");
            assert LVal != null;
            String param_ident = getIdent(LVal.getNode().get(0).getNode().get(0).getName());
            ArrayList<String> params = new ArrayList<>();
            for (int i = 2; i < LVal.getNode().size(); i += 3) {//获取参数
                params.add(get_Exp_Value(LVal.getNode().get(i), true));
            }
            String ptr = getArrayPtr(param_ident, params);
            out.write(var + " = call i32 @getarray(i32* " + ptr + ")\n");
            out.write(var_star + " = alloca i32\n");
            out.write("store i32 " + var + ", i32* " + var_star + "\n");
            varBlock.add_vars("$" + ident_name + get_num, var_star);
            exp.add("Ident($" + ident_name + get_num++ + ")");
        } else if (ident_name.equals("putarray")) {
            AST FuncRParams = node.getNode().get(2);
            if (FuncRParams.getNode().size() != 3) err("handle_FuncCall:putarray参数错误");
            String p1 = get_Exp_Value(FuncRParams.getNode().get(0), false);
            out.write(FuncRParams.getNode().get(0).getContent());//第一个参数n
            AST LVal = getAST(FuncRParams.getNode().get(2), "LVal");
            if (LVal == null) err("handle_FuncCall:getarray参数错误");
            String param_ident = getIdent(LVal.getNode().get(0).getNode().get(0).getName());
            ArrayList<String> params = new ArrayList<>();
            for (int i = 2; i < LVal.getNode().size(); i += 3) {//获取参数
                params.add(get_Exp_Value(LVal.getNode().get(i), true));
            }
            String p2 = getArrayPtr(param_ident, params);
            out.write("call void @putarray(i32 " + p1 + ", i32* " + p2 + ")\n");
        } else {//其他自定义函数调用
            func f = defined_func.get(ident_name);
            if (f == null) err("handle_FuncCall:使用了未定义的函数--> " + ident_name);
            assert f != null;
            if (f.funcType.equals("i32")) {//有返回值的
                String var = "%x" + var_num++;
                String var_star = "%x" + var_num++;
                if (node.getNode().size() == 3) {//无参数的
                    if (f.params_type.size() != 0) err("handle_FuncCall:使用了多余的参数--> " + ident_name);
                    out.write(var + " = call i32 @" + ident_name + "()\n");
                } else {//有参数的
                    AST FuncRParams = node.getNode().get(2);
                    if (f.params_type.size() != (FuncRParams.getNode().size() + 1) / 2)
                        err("handle_FuncCall:参数数量与定义不一致--> " + ident_name);
                    String str = write_FuncRParam(FuncRParams, f);//写参数
                    out.write(var + " = call i32 @" + ident_name + "(" + str + ")\n");
//                    out.write(var + " = call i32 @" + ident_name + "(");
//                    write_FuncRParam(FuncRParams, f);//写参数
//                    out.write(")\n");
                }
                out.write(var_star + " = alloca i32\n");
                out.write("store i32 " + var + ", i32* " + var_star + "\n");
                varBlock.add_vars("$" + ident_name + get_num, var_star);
                exp.add("Ident($" + ident_name + get_num++ + ")");
            } else {//无返回值的
                if (node.getNode().size() == 3) {//无参数的
                    out.write("call void @" + ident_name + "()\n");
                } else {//有参数的
                    AST FuncRParams = node.getNode().get(2);
                    if (f.params_type.size() != (FuncRParams.getNode().size() + 1) / 2)
                        err("handle_FuncCall:参数数量与定义不一致--> " + ident_name);
                    String str = write_FuncRParam(FuncRParams, f);//写参数
                    out.write("call void @" + ident_name + "(" + str + ")\n");
                }
            }
        }

    }

    //写函数调用的参数
    public String write_FuncRParam(AST FuncRParams, func f) throws IOException {
        ArrayList<String> p = new ArrayList<>();
        int size = f.params_type.size();
        for (int i = 0; i < size; i++) {
            AST exp = FuncRParams.getNode().get(2 * i);
            if (f.params_type.get(i).equals("i32")) {//说明是变量
                get_Exp_Value(exp, false);
                out.write(exp.getContent());//运算过程
                p.add("i32 " + exp.getVar());
            } else {//为i32*等,是数组
                AST LVal = getAST(exp, "LVal");
                if (LVal == null) err("write_FuncRParam:输入的参数不是数组");
                assert LVal != null;
                String ptr;
                String param_ident = getIdent(LVal.getNode().get(0).getNode().get(0).getName());
                if (varBlock.find_allArray(param_ident).type.equals(f.params_type.get(i))) {
                    ptr = varBlock.find_allArray(param_ident).var;
                } else {
                    ArrayList<String> params = new ArrayList<>();

                    for (int j = 2; j < LVal.getNode().size(); j += 3) {//获取参数
                        params.add(get_Exp_Value(LVal.getNode().get(j), false));
                        out.write(LVal.getNode().get(j).getContent());//写求值过程
                    }
                    ptr = getArrayPtr(param_ident, params);
                }
                p.add(f.params_type.get(i) + " " + ptr);
            }
        }
        return String.join(", ", p);
    }

    //获取putarray和getarray时array的指针.
    public String getArrayPtr(String ident, ArrayList<String> params) throws IOException {
        arrayIdent array = varBlock.find_allArray(ident);
        params.add("0");//加一个0,获取下一级的ptr
//        return getElement(ident, params, true, false);
        type t = getArrayType(array.dim);
        String type = t.toString();//内一级的type
        String var = "%x" + var_num++;
        out.write(var + " = getelementptr " + type + ", " + type + "* " + array.var + ", i32 0");
        for (String s : params) out.write(", i32 " + s);
        out.write("\n");
        return var;
    }

    // 提取ident
    public String getIdent(String ident) {
        Matcher m = Pattern.compile("\\(([a-zA-Z_0-9$:%]+)\\)").matcher(ident);
        String str = "";
        if (m.find()) {
            str = m.group();
            str = Pattern.compile("[()]").matcher(str).replaceAll("");
        }
        return str;
    }

    //寻找指定子节点
    public AST getAST(AST node, String name) {
        if (node.getName().equals(name))
            return node;
        else {
            if (node.getNode().size() > 0) {
                for (AST n : node.getNode()) {
                    AST a = getAST(n, name);
                    if (a != null) {
                        return a;
                    }
                }
            }
        }
        return null;
    }

    //判断是否为纯数字
    public boolean isNumber(String s) {
        return Pattern.compile("-?\\d+").matcher(s).matches();
    }

    //string转换成int
    public int to_int(String s) {
        return Integer.parseInt(s);
    }


    // 报错信息
    public void err(String message) {
        System.out.println(message);
        System.exit(1);
    }
}

class type {
    public String dim;
    public type innerType;

    public type(String dim, type innerType) {
        this.dim = dim;
        this.innerType = innerType;
    }

    public String toString() {
        if (innerType == null) {
            return "i32";
        } else if (dim.equals("0"))
            return innerType.toString();
        else
            return "[" + dim + " x " + innerType.toString() + "]";
    }
}

class func {
    public String ident;
    public String funcType;
    public ArrayList<String> params_type = new ArrayList<>();

    public func(String ident, String funcType) {
        this.ident = ident;
        this.funcType = funcType;
    }

}
